package com.hbsd.paopaobackend.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hbsd.paopaobackend.common.ErrorCode;
import com.hbsd.paopaobackend.exception.BusinessException;
import com.hbsd.paopaobackend.mapper.ApplyMapper;
import com.hbsd.paopaobackend.model.domain.Apply;
import com.hbsd.paopaobackend.model.domain.Friend;
import com.hbsd.paopaobackend.model.domain.User;
import com.hbsd.paopaobackend.model.request.Apply.AddApplyRequest;
import com.hbsd.paopaobackend.model.request.PageInfo;
import com.hbsd.paopaobackend.model.vo.Apply.ApplyListVO;
import com.hbsd.paopaobackend.model.vo.UserVO;
import com.hbsd.paopaobackend.service.ApplyService;
import com.hbsd.paopaobackend.service.FriendService;
import com.hbsd.paopaobackend.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zzh
 * @description 针对表【apply】的数据库操作Service实现

 */
@Service
public class ApplyServiceImpl extends ServiceImpl<ApplyMapper, Apply>
        implements ApplyService {

    @Resource
    private FriendService friendService;

    @Resource
    private UserService userService;

    /**
     * 添加申请
     *
     * @param applyRequest
     * @param loginUser
     * @return
     */
    @Override
    public Boolean addApply(AddApplyRequest applyRequest, User loginUser) {
        if (applyRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请信息不能为空");
        }
        Long uid = applyRequest.getUid();
        Long tid = applyRequest.getTid();
        if (uid == null || tid == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户id不饿能为空");
        }

        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN, "用户未登录");
        }

        // 查找好友表，看他们是否是好友
        // 如果是，直接抛出异常
        QueryWrapper<Apply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", uid);
        queryWrapper.eq("tid", tid);

        queryWrapper.or().eq("uid", tid).eq("tid", uid);
        Apply apply = this.getOne(queryWrapper);
        if (apply != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "已经申请过了");
        }


        User user1 = userService.getById(uid);
        User user2 = userService.getById(tid);

        if (user1 == null || user2 == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在");
        }

        if (user1.equals(user2)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "不能申请自己");
        }


        Apply apply1 = new Apply();
        apply1.setUid(uid);
        apply1.setTid(tid);

        return this.save(apply1);
    }


    /**
     * 分页查询申请列表
     *
     * @param pageInfo
     * @param loginUser
     * @return
     */
    @Override
    public Page<ApplyListVO> recommendUsers(PageInfo pageInfo, User loginUser) {
        // 校验参数
        if (pageInfo == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "分页信息不能为空");
        }
        // 校验用户是否登录
        if (loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN, "用户未登录");
        }
        // 找到该用户发送的申请和被申请的数据
        Long id = loginUser.getId();
        QueryWrapper<Apply> queryWrapper = new QueryWrapper<>();
        // 找到该用户发送请求和他被别人发送申请的数据
        // queryWrapper.eq("uid", id);
        // 申请人只要看到自己被申请的数据，而不是需要自己申请的数据
        // 简单来说就是， 甲向乙发起请求，甲这边不要看到好友申请，而是在乙这边看到好友申请
        queryWrapper.eq("tid", id);

        // 查询分页条件
        Page<Apply> page = new Page<>(pageInfo.getPageNum(), pageInfo.getPageSize());
        // 第一个参数就是 页码和页数
        // 第二个参数就是查询条件
        Page<Apply> applyPage = this.page(page, queryWrapper);


        // 转成VO，获取到用户的详细信息
        List<ApplyListVO> list = applyPage.getRecords().stream().map(apply -> {
            ApplyListVO applyListVO = new ApplyListVO();
            UserVO userVO1 = new UserVO();
            UserVO userVO2 = new UserVO();
            try {
                Long uid = apply.getUid();
                Long tid = apply.getTid();
                User uidUserInfo = userService.getById(uid);
                User tidUserInfo = userService.getById(tid);

                BeanUtil.copyProperties(uidUserInfo, userVO1, "tags");
                userVO1.setTags(Objects.nonNull(uidUserInfo.getTags()) ? JSONUtil.parseArray(uidUserInfo.getTags()).toList(String.class) : new ArrayList<>());
                BeanUtil.copyProperties(tidUserInfo, userVO2, "tags");
                userVO2.setTags(Objects.nonNull(tidUserInfo.getTags()) ? JSONUtil.parseArray(tidUserInfo.getTags()).toList(String.class) : new ArrayList<>());



            } catch (Exception e) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户信息转换失败");
            }
//            userVO1.setTags(JSONUtil.parseArray(userVO1.getTags()).toList(String.class));
//            userVO2.setTags(JSONUtil.parseArray(userVO2.getTags()).toList(String.class));


            applyListVO.setSendUserInfo(userVO1);
            applyListVO.setReceiveUserInfo(userVO2);
            applyListVO.setId(apply.getId());
            return applyListVO;
        }).collect(Collectors.toList());

        Page<ApplyListVO> applyListVOPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        applyListVOPage.setRecords(list);
        return applyListVOPage;
    }

    /**
     * 通过好友申请
     *
     * @param id
     * @param loginUser
     * @return
     */

    // 开启事务 有一个表没有操作成功，对应者表也不会做修改
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean passApply(Long id, User loginUser) {
        if (id == null || id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请id不能为空");
        }

        if(loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN, "用户未登录");
        }

        // 先找到该用户申请的这条数据，然后获取到对应的uid和tid，最后赋值給friend表中，要赋值2次(反向的)_
        Apply apply = this.getById(id);
        if (apply == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请不存在");
        }
        Long uid = apply.getUid();
        Long tid = apply.getTid();


        QueryWrapper<Friend> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("uid", uid);
        queryWrapper.eq("fid", tid);
        Friend friend = friendService.getOne(queryWrapper);
        if (friend != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "已经是好友了");
        }

        Friend friend1 = new Friend();
        friend1.setUid(uid);
        friend1.setFid(tid);

        boolean save1 = friendService.save(friend1);

        Friend friend2 = new Friend();
        friend2.setUid(tid);
        friend2.setFid(uid);

        boolean save2 = friendService.save(friend2);

        if(!save1 && !save2) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "好友关系保存失败");
        }


        // 最后删除该条申请数据
        apply.setIsDelete(1);
        boolean result = this.removeById(apply);
        if(!result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "更新失败");
        }
        return true;

    }

    /**
     * 拒绝好友申请
     * @param id
     * @param loginUser
     * @return
     */
    @Override
    public Boolean deleteApply(long id, User loginUser) {
       if(id <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请id不能为空");
       }

       if(loginUser == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN, "用户未登录");
       }

       Apply apply = this.getById(id);
       if(apply == null) {
           throw new BusinessException(ErrorCode.PARAMS_ERROR, "申请不存在");
       }



        boolean result = this.removeById(id);
        if(!result) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "删除失败");
        }
        return true;


    }
}




